package collector

import (
	"context"
	"github.com/go-kit/kit/log"
	"github.com/go-redis/redis/v8"
	"github.com/prometheus/client_golang/prometheus"
	"strconv"
)

// 基本活动指标
// connected_clients 客户端连接数
// connected_laves slave数量
// master_last_io_seconds_ago 最近一次主从交互之后的秒数
// keyspace 数据库中的key值总数
const (
	// Subsystem.
	activity = "activity"
	//
	connectedClients       = "connected_clients"
	connectedSlaves        = "connected_slaves"
	masterLastIoSecondsAgo = "master_last_io_seconds_ago"
	keySpace               = "keyspace"
)

// Metric descriptors.
var (
	connectedClientsDesc = prometheus.NewDesc(
		prometheus.BuildFQName(namespace, activity, connectedClients),
		"客户端连接数",
		[]string{}, nil,
	)
	connectedLavesDesc = prometheus.NewDesc(
		prometheus.BuildFQName(namespace, activity, connectedSlaves),
		"slave数量",
		[]string{}, nil,
	)
	masterLastIoSecondsAgoDesc = prometheus.NewDesc(
		prometheus.BuildFQName(namespace, activity, masterLastIoSecondsAgo),
		"最近一次主从交互之后的秒数",
		[]string{}, nil,
	)
	keySpaceDesc = prometheus.NewDesc(
		prometheus.BuildFQName(namespace, activity, keySpace),
		"数据库中的key值总数",
		[]string{}, nil,
	)
)

// ScrapeActivity collects from performance.
type ScrapeActivity struct{}

// Name of the Scraper. Should be unique.
func (ScrapeActivity) Name() string {
	return activity
}

// Help describes the role of the Scraper.
func (ScrapeActivity) Help() string {
	return "Collect the current size of all registered binlog files"
}

// Version of Redis from which scraper is available.
func (ScrapeActivity) Version() float64 {
	return 4.0
}

// Scrape collects data from redis connection and sends it over channel as prometheus metric.
func (ScrapeActivity) Scrape(ctx context.Context, client *redis.Client, ch chan<- prometheus.Metric, logger log.Logger) error {

	data, err := infos(client, "clients", "replication")
	if err != nil {
		return err
	}

	clients := valueOf(data, connectedClients)
	slaves := valueOf(data, connectedSlaves)
	masterLast := valueOf(data, masterLastIoSecondsAgo)

	// keys数量
	keySpaces, err := infos(client, keySpace)
	if err != nil {
		return err
	}

	sum := 0
	for _, keyspace := range keySpaces {
		ksMap := formatStrReply(keyspace, ",", "=")
		keys, err := strconv.Atoi(ksMap["keys"])
		if err == nil {
			sum += keys
		}
	}

	ch <- prometheus.MustNewConstMetric(
		connectedClientsDesc, prometheus.GaugeValue, clients,
	)
	ch <- prometheus.MustNewConstMetric(
		connectedLavesDesc, prometheus.GaugeValue, slaves,
	)

	ch <- prometheus.MustNewConstMetric(
		masterLastIoSecondsAgoDesc, prometheus.GaugeValue, masterLast,
	)

	ch <- prometheus.MustNewConstMetric(
		keySpaceDesc, prometheus.GaugeValue, float64(sum),
	)

	return nil
}

// check interface
var _ Scraper = ScrapeActivity{}
